home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / sys5 / iscwmpst.z / iscwmpst / tcp / src / ttydriv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-10  |  9.9 KB  |  478 lines

  1. /* @(#) $Header: ttydriv.c,v 1.11 91/10/08 12:54:52 deyke Exp $ */
  2.  
  3. /* TTY input line editing
  4.  */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8.  
  9. #include "global.h"
  10. #include "tty.h"
  11.  
  12. #define LINESIZE     1024
  13. #define LINEMAX      (LINESIZE-5)
  14. #define RECALLSIZE   63
  15.  
  16. #define NEXT(i)      (((i) + 1) & RECALLSIZE)
  17. #define PREV(i)      (((i) - 1) & RECALLSIZE)
  18.  
  19. char *Fkey_table[NUM_FKEY];
  20. char *Fkey_ptr;
  21.  
  22. static int  ansimode;
  23. static int  rawmode;
  24.  
  25. static void printchr __ARGS((int chr));
  26. static void backchr __ARGS((int chr));
  27. static void delchr __ARGS((int chr));
  28. static void inschr __ARGS((int chr));
  29.  
  30. /*---------------------------------------------------------------------------*/
  31.  
  32. int  raw()
  33. {
  34.   rawmode = 1;
  35.   return 0;
  36. }
  37.  
  38. /*---------------------------------------------------------------------------*/
  39.  
  40. int  cooked()
  41. {
  42.   rawmode = 0;
  43.   return 0;
  44. }
  45.  
  46. /*---------------------------------------------------------------------------*/
  47.  
  48. static void printchr(chr)
  49. int  chr;
  50. {
  51.   chr &= 0xff;
  52.   if (chr < 32) {
  53.     putchar('^');
  54.     putchar(chr + 64);
  55.   } else if (chr < 127) {
  56.     putchar(chr);
  57.   } else if (chr < 128) {
  58.     putchar('^');
  59.     putchar('?');
  60.   } else if (chr < 159) {
  61.     putchar('^');
  62.     putchar(chr - 32);
  63.   } else if (chr < 160) {
  64.     putchar('^');
  65.     putchar('>');
  66.   } else if (chr < 255) {
  67.     putchar(chr);
  68.   } else {
  69.     putchar('^');
  70.     putchar('/');
  71.   }
  72. }
  73.  
  74. /*---------------------------------------------------------------------------*/
  75.  
  76. static void backchr(chr)
  77. int  chr;
  78. {
  79.   putchar('\b');
  80.   chr &= 0x7f;
  81.   if (chr < 32 || chr == 127)
  82.     putchar('\b');
  83. }
  84.  
  85. /*---------------------------------------------------------------------------*/
  86.  
  87. static void delchr(chr)
  88. int  chr;
  89. {
  90.   putchar('\033');
  91.   if (ansimode) putchar('[');
  92.   putchar('P');
  93.   chr &= 0x7f;
  94.   if (chr < 32 || chr == 127) {
  95.     putchar('\033');
  96.     if (ansimode) putchar('[');
  97.     putchar('P');
  98.   }
  99. }
  100.  
  101. /*---------------------------------------------------------------------------*/
  102.  
  103. static void inschr(chr)
  104. int  chr;
  105. {
  106.   int  c;
  107.  
  108.   if (ansimode) {
  109.     c = chr & 0x7f;
  110.     printf("\033[%d@", (c < 32 || c == 127) ? 2 : 1);
  111.     printchr(chr);
  112.   } else {
  113.     putchar('\033');
  114.     putchar('Q');
  115.     printchr(chr);
  116.     putchar('\033');
  117.     putchar('R');
  118.   }
  119. }
  120.  
  121. /*---------------------------------------------------------------------------*/
  122.  
  123. /* Accept characters from the incoming tty, buffer and process them
  124.  * (if in cooked mode) or just pass them directly (if in raw mode).
  125.  * Returns the number of characters available for use; if non-zero,
  126.  * also stashes a pointer to the character(s) in the "buf" argument.
  127.  */
  128.  
  129. int  ttydriv(chr, buf)
  130. int  chr;
  131. char  **buf;
  132. {
  133.  
  134.   static char  linebuf[LINESIZE];
  135.   static char  *end = linebuf;
  136.   static char  *pos = linebuf;
  137.   static char  *recall_buffer[RECALLSIZE+1];
  138.   static int  Escape_save;
  139.   static int  ansikey;
  140.   static int  esc, quote;
  141.   static int  rptr, wptr;
  142.  
  143.   char  *p, *f, *t;
  144.   int  cnt;
  145.  
  146.   if (rawmode) {
  147.     *linebuf = chr;
  148.     *buf = linebuf;
  149.     return 1;
  150.   }
  151.  
  152.   if (!chr) return 0;
  153.   cnt = 0;
  154.   if (quote) {
  155.     delchr(quote);
  156.     quote = 0;
  157.     Escape = Escape_save;
  158.     if (pos == end) {
  159.       *end++ = chr;
  160.       printchr(*pos++);
  161.     } else {
  162.       for (p = end - 1; p >= pos; p--) p[1] = *p;
  163.       *pos++ = chr;
  164.       end++;
  165.       inschr(chr);
  166.     }
  167.   } else if (ansikey) {
  168.     ansikey = 0;
  169.     switch (chr) {
  170.  
  171.     case 'A': /* up arrow */
  172.       if (recall_buffer[PREV(rptr)]) {
  173.     if (end > linebuf) {
  174.       while (pos > linebuf) backchr(*--pos);
  175.       putchar('\033');
  176.       putchar('K');
  177.     }
  178.     rptr = PREV(rptr);
  179.     strcpy(linebuf, recall_buffer[rptr]);
  180.     for (pos = linebuf; *pos; pos++) printchr(*pos);
  181.     end = pos;
  182.       } else
  183.     putchar(7);
  184.       break;
  185.  
  186.     case 'B': /* down arrow */
  187.       if (recall_buffer[rptr] && recall_buffer[NEXT(rptr)]) {
  188.     if (end > linebuf) {
  189.       while (pos > linebuf) backchr(*--pos);
  190.       putchar('\033');
  191.       putchar('K');
  192.     }
  193.     rptr = NEXT(rptr);
  194.     strcpy(linebuf, recall_buffer[rptr]);
  195.     for (pos = linebuf; *pos; pos++) printchr(*pos);
  196.     end = pos;
  197.       } else
  198.     putchar(7);
  199.       break;
  200.  
  201.     case 'C': /* cursor right */
  202.       if (pos - linebuf >= LINEMAX)
  203.     putchar(7);
  204.       else {
  205.     if (pos == end) *end++ = ' ';
  206.     printchr(*pos++);
  207.       }
  208.       break;
  209.  
  210.     case 'D': /* cursor left */
  211.       if (pos > linebuf) backchr(*--pos);
  212.       break;
  213.  
  214.     case 'P': /* ansi function key 1 */
  215.       Fkey_ptr = Fkey_table[0];
  216.       break;
  217.  
  218.     case 'Q': /* ansi function key 2 */
  219.       Fkey_ptr = Fkey_table[1];
  220.       break;
  221.  
  222.     case 'R': /* ansi function key 3 */
  223.       Fkey_ptr = Fkey_table[2];
  224.       break;
  225.  
  226.     case 'S': /* ansi function key 4 */
  227.       Fkey_ptr = Fkey_table[3];
  228.       break;
  229.  
  230.     case 'T': /* ansi function key 5 */
  231.     case 'w': /* ansi function key 5 */
  232.       Fkey_ptr = Fkey_table[4];
  233.       break;
  234.  
  235.     case 'U': /* ansi function key 6 */
  236.     case 'x': /* ansi function key 6 */
  237.       Fkey_ptr = Fkey_table[5];
  238.       break;
  239.  
  240.     case 'V': /* ansi function key 7 */
  241.     case 'y': /* ansi function key 7 */
  242.       Fkey_ptr = Fkey_table[6];
  243.       break;
  244.  
  245.     case 'W': /* ansi function key 8 */
  246.     case 'm': /* ansi function key 8 */
  247.       Fkey_ptr = Fkey_table[7];
  248.       break;
  249.  
  250.     case 'X': /* ansi function key 9 */
  251.     case 't': /* ansi function key 9 */
  252.       Fkey_ptr = Fkey_table[8];
  253.       break;
  254.  
  255.     case 'Y': /* ansi function key 10 */
  256.     case 'u': /* ansi function key 10 */
  257.       Fkey_ptr = Fkey_table[9];
  258.       break;
  259.  
  260.     }
  261.   } else if (!esc) {
  262.     switch (chr) {
  263.  
  264.     case '\b': /* backspace */
  265.       if (pos > linebuf) {
  266.     backchr(*--pos);
  267.     delchr(*pos);
  268.     for (p = pos + 1; p < end; p++) p[-1] = *p;
  269.     end--;
  270.       }
  271.       break;
  272.  
  273.     case '\n': /* linefeed */
  274.     case '\r': /* return */
  275.     case 20:   /* control T, transmit line */
  276.       *end = '\0';
  277.       if (*linebuf && strcmp(linebuf, recall_buffer[PREV(wptr)])) {
  278.     recall_buffer[wptr] = strcpy(malloc(end - linebuf + 1), linebuf);
  279.     wptr = NEXT(wptr);
  280.     if (recall_buffer[wptr]) {
  281.       free(recall_buffer[wptr]);
  282.       recall_buffer[wptr] = 0;
  283.     }
  284.       }
  285.       rptr = wptr;
  286.       if (chr != 20) {
  287.     *end++ = '\r';
  288.     *end++ = '\n';
  289.     *end   = '\0';
  290.     putchar('\n');
  291.       }
  292.       cnt = end - linebuf;
  293.       pos = end = linebuf;
  294.       break;
  295.  
  296.     case 18: /* control R, redisplay line */
  297.       putchar('\n');
  298.       for (p = linebuf; p < end; p++) printchr(*p);
  299.       while (p > pos) backchr(*--p);
  300.       break;
  301.  
  302.     case 21: /* control U, delete line */
  303.     case 24: /* control X, delete line */
  304.       if (end > linebuf) {
  305.     while (pos > linebuf) backchr(*--pos);
  306.     end = linebuf;
  307.     putchar('\033');
  308.     if (ansimode) putchar('[');
  309.     putchar('K');
  310.       }
  311.       break;
  312.  
  313.     case 22: /* control V, quote next character */
  314.       if (end - linebuf >= LINEMAX)
  315.     putchar(7);
  316.       else {
  317.     Escape_save = Escape;
  318.     Escape = 0;
  319.     quote = '^';
  320.     if (pos == end)
  321.       printchr(quote);
  322.     else
  323.       inschr(quote);
  324.     backchr(quote);
  325.       }
  326.       break;
  327.  
  328.     case 23: /* control W, delete word */
  329.       p = pos;
  330.       while (p > linebuf && p[-1] == ' ') { backchr(*--p); delchr(*p); }
  331.       while (p > linebuf && p[-1] != ' ') { backchr(*--p); delchr(*p); }
  332.       for (f = pos, t = p; f < end; ) *t++ = *f++;
  333.       pos = p;
  334.       end = t;
  335.       break;
  336.  
  337.     case 27: /* escape */
  338.       esc = 1;
  339.       ansimode = 0;
  340.       break;
  341.  
  342.     case 127: /* DEL, delete char */
  343.       if (pos < end) {
  344.     delchr(*pos);
  345.     for (p = pos + 1; p < end; p++) p[-1] = *p;
  346.     end--;
  347.       }
  348.       break;
  349.  
  350.     default:
  351.       if (end - linebuf >= LINEMAX)
  352.     putchar(7);
  353.       else if (pos == end) {
  354.     *end++ = chr;
  355.     printchr(*pos++);
  356.       } else {
  357.     for (p = end - 1; p >= pos; p--) p[1] = *p;
  358.     *pos++ = chr;
  359.     end++;
  360.     inschr(chr);
  361.       }
  362.       break;
  363.  
  364.     }
  365.   } else {
  366.     esc = 0;
  367.     switch (chr) {
  368.  
  369.     case 'A': /* up arrow */
  370.     case 'V': /* prev page */
  371.       if (recall_buffer[PREV(rptr)]) {
  372.     if (end > linebuf) {
  373.       while (pos > linebuf) backchr(*--pos);
  374.       putchar('\033');
  375.       if (ansimode) putchar('[');
  376.       putchar('K');
  377.     }
  378.     rptr = PREV(rptr);
  379.     strcpy(linebuf, recall_buffer[rptr]);
  380.     for (pos = linebuf; *pos; pos++) printchr(*pos);
  381.     end = pos;
  382.       } else
  383.     putchar(7);
  384.       break;
  385.  
  386.     case 'B': /* down arrow */
  387.     case 'U': /* next page */
  388.       if (recall_buffer[rptr] && recall_buffer[NEXT(rptr)]) {
  389.     if (end > linebuf) {
  390.       while (pos > linebuf) backchr(*--pos);
  391.       putchar('\033');
  392.       if (ansimode) putchar('[');
  393.       putchar('K');
  394.     }
  395.     rptr = NEXT(rptr);
  396.     strcpy(linebuf, recall_buffer[rptr]);
  397.     for (pos = linebuf; *pos; pos++) printchr(*pos);
  398.     end = pos;
  399.       } else
  400.     putchar(7);
  401.       break;
  402.  
  403.     case 'C': /* cursor right */
  404.       if (pos - linebuf >= LINEMAX)
  405.     putchar(7);
  406.       else {
  407.     if (pos == end) *end++ = ' ';
  408.     printchr(*pos++);
  409.       }
  410.       break;
  411.  
  412.     case 'D': /* cursor left */
  413.       if (pos > linebuf) backchr(*--pos);
  414.       break;
  415.  
  416.     case 'F': /* cursor home down */
  417.     case 'Y': /* end */
  418.       while (pos < end) printchr(*pos++);
  419.       break;
  420.  
  421.     case 'H': /* cursor home up */
  422.     case 'h': /* cursor home up */
  423.       while (pos > linebuf) backchr(*--pos);
  424.       break;
  425.  
  426.     case 'J': /* clear display */
  427.     case 'M': /* delete line */
  428.       while (pos > linebuf) backchr(*--pos);
  429.     case 'K': /* clear line */
  430.       if (end > pos) {
  431.     end = pos;
  432.     putchar('\033');
  433.     if (ansimode) putchar('[');
  434.     putchar('K');
  435.       }
  436.       break;
  437.  
  438.     case 'O': /* ansi arrow or function key */
  439.       ansimode = ansikey = 1;
  440.       break;
  441.  
  442.     case 'P': /* delete char */
  443.       if (pos < end) {
  444.     delchr(*pos);
  445.     for (p = pos + 1; p < end; p++) p[-1] = *p;
  446.     end--;
  447.       }
  448.       break;
  449.  
  450.     case '[': /* ansi escape sequence */
  451.       esc = ansimode = 1;
  452.       break;
  453.  
  454.     case 'p': /* hp function key 1 */
  455.     case 'q': /* hp function key 2 */
  456.     case 'r': /* hp function key 3 */
  457.     case 's': /* hp function key 4 */
  458.     case 't': /* hp function key 5 */
  459.     case 'u': /* hp function key 6 */
  460.     case 'v': /* hp function key 7 */
  461.     case 'w': /* hp function key 8 */
  462.       Fkey_ptr = Fkey_table[chr - 'p'];
  463.       break;
  464.  
  465.     default:
  466.       putchar('\033');
  467.       if (ansimode) putchar('[');
  468.       putchar(chr);
  469.       break;
  470.  
  471.     }
  472.   }
  473.   fflush(stdout);
  474.   if (cnt) *buf = linebuf;
  475.   return cnt;
  476. }
  477.  
  478.